/**
 * @file meridian_time.cpp
 * @brief Brief description of meridian_time.cpp
 * @author achdu0000@163.com
 * @version 1.0.0
 * @date 2024/07/07
 */

#include "meridian_time.h"

// ==================================================
// =============== PRE-DECLARE ======================
// ==================================================

LV_IMG_DECLARE(img_hand_min_h150)
LV_IMG_DECLARE(img_hand_hour_h130)

LV_FONT_DECLARE(lv_font_yahei_bold_18)
LV_FONT_DECLARE(lv_font_yahei_bold_12)

// ==================================================
// =============== DEFINATIONS ======================
// ==================================================

#define HOUR_VAL_TO_SHOW(h_v) ((h_v % 12 == 0) ? 12 : (h_v % 12))
#define MIN_VAL_TO_SHOW(m_v) (m_v)
#define GET_MIN_A(min_val) ((min_val - 4 < 0) ? min_val + 56 : min_val - 4)

// ==================================================
// =============== STATIC VARIABLES =================
// ==================================================

static uint16_t min_scale_width = 1;
static uint16_t min_scale_len = 16;
static uint16_t hour_scale_width = 3;
static uint16_t hour_scale_len = 20;
static lv_color_t min_scale_color = SCREEN_FG_COLOR;
static lv_color_t hour_scale_color = SCREEN_FG_COLOR;

static lv_obj_t *hour_and_minute_clock_meter = nullptr;

static lv_obj_t *time_text_label = nullptr;

static lv_meter_indicator_t *indic_min_assitant = nullptr;

static lv_meter_indicator_t *indic_min = nullptr;

static lv_meter_indicator_t *indic_hour = nullptr;

static lv_obj_t *label_meridian = nullptr;

static uint16_t year_val = 0;
static uint8_t month_val = 0;
static uint8_t day_val = 0;
static uint8_t hour_val = 0;
static uint8_t min_val = 0;

static const char *hour_ganzhi_str = nullptr;

static lv_timer_t *update_time_timer = nullptr;

static lv_timer_t *update_open_meridian_timer = nullptr;

// ==================================================
// =============== STATIC FUNCTION ==================
// ==================================================

static void update_timer_xcb(lv_timer_t *timer);

static void update_open_meridian_xcb(lv_timer_t *timer);

// ==================================================
// =============== IMPLEMENTATION ===================
// ==================================================

lv_timer_t *get_timer1()
{
    return update_time_timer;
}

lv_timer_t *get_timer2()
{
    return update_open_meridian_timer;
}

lv_obj_t *get_basic_hour_and_minute_clock_meter_obj()
{
    return hour_and_minute_clock_meter;
}

lv_obj_t *get_hour_and_minute_clock()
{
    return hour_and_minute_clock_meter;
}

uint16_t get_year_val()
{
    return year_val;
}

uint8_t get_month_val()
{
    return month_val;
}

uint8_t get_day_val()
{
    return day_val;
}

uint8_t get_hour_val()
{
    return hour_val;
}

uint8_t get_min_val()
{
    return min_val;
}

bool set_now_time_val(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min)
{
    year_val = year;
    month_val = month;
    day_val = day;
    hour_val = hour;
    min_val = min;
    return true;
}

bool set_now_hour_ganzhi(const char *hour_ganzhi_s)
{
    hour_ganzhi_str = hour_ganzhi_s;
    return true;
}

const char *get_now_hour_ganzhi()
{
    return hour_ganzhi_str;
}

bool create_basic_hour_and_minute_clock_ui(lv_obj_t *parent, lv_coord_t width, lv_coord_t height, lv_coord_t *content_w_ptr, lv_coord_t *content_h_ptr)
{
    hour_and_minute_clock_meter = lv_meter_create(parent);
    lv_obj_set_size(hour_and_minute_clock_meter, width, height);
    lv_obj_set_style_bg_opa(hour_and_minute_clock_meter, LV_OPA_TRANSP, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_center(hour_and_minute_clock_meter);

    /*Remove the circle from the middle of `hour_and_minute_clock_meter`*/
    lv_obj_remove_style(hour_and_minute_clock_meter, nullptr, LV_PART_INDICATOR);
    /*Remove the padding from `hour_and_minute_clock_meter` (especially the padding between ticks and borader)*/
    lv_obj_set_style_pad_all(hour_and_minute_clock_meter, 0, LV_PART_MAIN | LV_STATE_DEFAULT);

    lv_meter_scale_t *min_scale = lv_meter_add_scale(hour_and_minute_clock_meter);
    lv_meter_set_scale_ticks(hour_and_minute_clock_meter, min_scale, 61, min_scale_width, min_scale_len, min_scale_color);
    lv_meter_set_scale_range(hour_and_minute_clock_meter, min_scale, 0, 60, 360, 270);

    lv_meter_scale_t *hour_scale = lv_meter_add_scale(hour_and_minute_clock_meter);
    lv_meter_set_scale_ticks(hour_and_minute_clock_meter, hour_scale, 12, 0, 0, hour_scale_color);
    lv_meter_set_scale_range(hour_and_minute_clock_meter, hour_scale, 1, 12, 330, 300);
    lv_obj_set_style_text_font(hour_and_minute_clock_meter, &lv_font_montserrat_24, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_meter_set_scale_major_ticks(hour_and_minute_clock_meter, hour_scale, 1, hour_scale_width, hour_scale_len, hour_scale_color, 8);

    /*Add a the hands from images*/

    indic_min_assitant = lv_meter_add_needle_line(hour_and_minute_clock_meter, min_scale, 2, SCREEN_FG_COLOR, -25);
    lv_meter_set_indicator_value(hour_and_minute_clock_meter, indic_min_assitant, MIN_VAL_TO_SHOW(GET_MIN_A(min_val)));

    indic_min = lv_meter_add_needle_img(hour_and_minute_clock_meter, min_scale, &img_hand_min_h150, 5, 5);
    lv_meter_set_indicator_end_value(hour_and_minute_clock_meter, indic_min, MIN_VAL_TO_SHOW(min_val));

    indic_hour = lv_meter_add_needle_img(hour_and_minute_clock_meter, hour_scale, &img_hand_hour_h130, 5, 5);
    lv_meter_set_indicator_end_value(hour_and_minute_clock_meter, indic_hour, HOUR_VAL_TO_SHOW(hour_val));

    time_text_label = lv_label_create(parent);
    lv_obj_set_style_text_font(time_text_label, &lv_font_yahei_bold_18, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(time_text_label, lv_color_white(), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(time_text_label, lv_palette_main(LV_PALETTE_PURPLE), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(time_text_label, LV_OPA_COVER, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_label_set_text_fmt(time_text_label, "%d年%02d月%02d日%02d:%02d", year_val, month_val, day_val, hour_val, min_val);
    lv_obj_align_to(time_text_label, parent, LV_ALIGN_CENTER, 0, -120);

    *content_w_ptr = width;
    *content_h_ptr = height;

    update_time_timer = lv_timer_create(update_timer_xcb, UNIT_TIME_MS, nullptr);
    lv_timer_set_repeat_count(update_time_timer, -1);
    // lv_timer_ready(update_time_timer);

    return true;
}

bool create_extend_2_hour_ganzhi_and_open_meridian_label_ui(lv_obj_t *parent, lv_coord_t x_ofs, lv_coord_t y_ofs)
{
    lv_obj_t *label = lv_label_create(parent);
    lv_label_set_text_fmt(label, "【经时-时】%s·", get_now_hour_ganzhi());
    lv_obj_set_style_text_font(label, &lv_font_yahei_bold_12, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(label, lv_color_make(112, 48, 160), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_align_to(label, parent, LV_ALIGN_CENTER, x_ofs, y_ofs);

    uint8_t open_meridian_index = ((hour_val > 22 || hour_val < 1) ? 0 : (hour_val + 1) / 2);
    label_meridian = lv_label_create(parent);
    lv_label_set_text_fmt(label_meridian, "%s", twelve_meridian_text_table[open_meridian_index]);
    lv_obj_set_style_text_font(label_meridian, &lv_font_yahei_bold_12, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_color(label_meridian, get_wuxing_color(twelve_meridian_wuxing_table[open_meridian_index]), LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_set_style_text_align(label_meridian, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN | LV_STATE_DEFAULT);
    lv_obj_align_to(label_meridian, label, LV_ALIGN_OUT_RIGHT_MID, 0, 0);

    update_open_meridian_timer = lv_timer_create(update_open_meridian_xcb, UNIT_TIME_MS, nullptr);
    lv_timer_set_repeat_count(update_open_meridian_timer, -1);
    lv_timer_ready(update_open_meridian_timer);

    return true;
}

static void update_timer_xcb(lv_timer_t *timer)
{
    min_val++;
    if (min_val == 60)
    {
        min_val = 0;
        hour_val++;
        if (hour_val == 24)
        {
            hour_val = 0;
            day_val++;
            if (day_val == 32)
            {
                day_val = 1;
                month_val++;
                if (month_val == 13)
                {
                    month_val = 1;
                    year_val++;
                }
            }
        }
    }
    lv_meter_set_indicator_end_value(hour_and_minute_clock_meter, indic_min, MIN_VAL_TO_SHOW(min_val));
    lv_meter_set_indicator_end_value(hour_and_minute_clock_meter, indic_hour, HOUR_VAL_TO_SHOW(hour_val));
    lv_label_set_text_fmt(time_text_label, "%d年%02d月%02d日%02d:%02d", year_val, month_val, day_val, hour_val, min_val);

    uint8_t open_meridian_index = ((hour_val > 22 || hour_val < 1) ? 0 : (hour_val + 1) / 2);
    lv_label_set_text_fmt(label_meridian, "%s", twelve_meridian_text_table[open_meridian_index]);
    lv_obj_set_style_text_color(label_meridian, get_wuxing_color(twelve_meridian_wuxing_table[open_meridian_index]), LV_PART_MAIN | LV_STATE_DEFAULT);
}

static void update_open_meridian_xcb(lv_timer_t *timer)
{
    lv_meter_set_indicator_value(hour_and_minute_clock_meter, indic_min_assitant, MIN_VAL_TO_SHOW(GET_MIN_A(min_val)));
}